from mongoengine import *
from bson import ObjectId
from db import *
import json
import world



def is_user_exist(name,pwd):
    it = User.objects(Q(name=name) & Q(pwd=pwd)).first()
    return True if it is not None else False

def is_username_duplicated(name):
    it = User.objects(Q(name=name)).first()
    return True if it is not None else False

def get_user_by_name(name):
  return User.objects(name=name).first()

def login(data,client):
    print('Is login')
    if is_user_exist(data['user'],data['pass']):
      print('Login succeed')
      client.user = get_user_by_name(data['user'])
      return {'ok': True}
    else:
      print('Login fail')
      client.user = None
      return {'ok': False}

def get_player(username):
  return Player.objects(username=username).first()

def get_player_by_id(id):
  return Player.objects(_id=id).first()

def initial_player(username, nick):
  # area_id is point to orchard of beginer_village
  church = Area.objects(name="church").first()
  return Player(name=nick, power=5, level=1, growth_factor=5, exp=0, username=username, area_id=beginer_village._id, hp=20, max_hp=20, online=False, dead_time=-1 )

def offlinePlayer(client):
  player = get_player_by_id(client.player._id)
  player.online = False
  player.save()
  # broadcast
  world.forceRefreshPlayers(client.factory, str(player.area_id))


def dispatch(data,client):
  print(str(data))
  url = data['url']
  res = {}

  if url == 'login':
    res = login(data,client)
  elif url == 'player': # Only call once after player login
    player = get_player(data['id'])
    # If user hasn't player then create initial player
    if player is None:
      player = initial_player(username=data['id'], nick=client.user.nick)
      # player.save()
    player.online = True # Update online status
    player.save()
    # Broadcast update players
    world.forceRefreshPlayers(client.factory,str(player.area_id))
    res['player'] = player.dict()
    # Store to the client
    client.player = player
  elif url == 'position':
    pos = Area.objects(__raw__={'_id': ObjectId(data['id'])}).first()
    res = pos.dict()
  elif url == 'sub_positions':
    sub_poses = Area.objects(__raw__={'pid': ObjectId(data['pid'])})
    res['positions'] = map(lambda x: x.dict() , sub_poses)
  elif url == 'lives':
    # world.forcePositionPlayersRefreshMap(client.factory, data['id'])
    res.update(world.lives(data['id']))
  elif url == 'move':
    Player.objects(username=client.user.name).update_one(area_id=data['area_id'])
    world.forceRefreshPlayers(client.factory, data['src_area_id']) 
    world.forceRefreshPlayers(client.factory, data['area_id']) 
    res['ok'] = True
  elif url == 'register':
    if is_username_duplicated(data['name']):
      res['ok'] = False
      res['err'] = 'Username duplicated!'
    else:
      user = User(name=data['name'], pwd=data['pass'], nick=data['nick'])
      user.save()
      res['ok'] = True
  elif url == 'attack_mob':
    player = get_player_by_id(client.player._id)
    mob = Mob.objects(__raw__={'_id': ObjectId(data['mob_id'])}).first()
    refreshPlayer = player.dict()
    result = world.attack_mob(mob, player, client.factory.worldTime, client)
    res['result'] = result

    # Anouncing all players in the area
    [src,tar] = [player,mob] if result['win'] else [mob,player]
    world.positionAnounce(client.factory,refreshPlayer['area_id'],' '.join([src.name,'killed',tar.name]))

    # Force client update player info
    world.forcePositionPlayersRefreshMap(client.factory, player.area_id)
  elif url == 'attack_player':
    tar = Player.objects(__raw__={'_id': ObjectId(data['player_id'])}).first()
    src = get_player_by_id(client.player._id)
    world.attack_player(src,tar,client.factory)
    return None

  elif url == 'inventory':
    world.forceRefreshInventory(client)
    return None
  elif url == 'item':
    item = Item.objects(__raw__={'_id': ObjectId(data['id'])}).first()
    res['item'] = item.dict()
  elif url == 'equip':
    equip = Equip.objects(__raw__={'_id': ObjectId(data['id'])}).first()
    res['equip'] = equip.dict()
  
  elif url == 'use_item':
    inventoryId = data['id']
    result = world.useItem(client,inventoryId)
    if result['ok']:
      world.inventoryNumDecrease(inventoryId)
      res['ok'] = True
      # Refresh inventory of player
      world.forceRefreshInventory(client)
    else:
      # world.anounceToPlayer(client, ' '.join(['Use item failed: ',result['err']]), 'warn')
      res['ok'] = False
      res['err'] = result['err']

  elif url == 'spawn':
    name = data['name']
    num = data['num']
    world.spawnMob(name,num)
    res['ok'] = True

  elif url == 'wear_equip':
    inventoryId = data['id']
    result = world.wearEquip(inventoryId, client)
    res['ok'] = True

  elif url == 'equiping':
    world.forceRefreshEquiping(client)
    return None

  elif url == 'take_off':
    world.takeOffEquip(data['id'], client)
    res['ok'] = True

  else:
    print('Is not login')

  res['url'] = url
  client.sendMessage(json.dumps(res))